// app/utils/utils.go
package utils

import (
	"BlazeRider-backend/app/models"
	"bytes"
	"context"
	"crypto/hmac"
	"crypto/sha256"
	"database/sql"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/google/uuid"
	"io"
	"net/http"
	"net/url"
	"sort"
	"strings"
	"time"
)

// ================== HTTP 工具方法 ==================

// Get 通用GET请求
// targetURL: 完整请求地址（参数重命名避免冲突）
func Get(targetURL string, params map[string]string, signSecret string, result interface{}) error {
	// 参数签名
	if signSecret != "" {
		params = signParams(params, signSecret)
	}

	// 构建请求URL（使用重命名后的参数）
	parsedURL, err := url.Parse(targetURL)
	if err != nil {
		return fmt.Errorf("url parse error: %w", err)
	}

	// 添加查询参数
	query := parsedURL.Query()
	for k, v := range params {
		query.Add(k, v)
	}
	parsedURL.RawQuery = query.Encode()
	// 创建带超时的客户端
	client := &http.Client{Timeout: 30 * time.Second}

	// 重试逻辑
	var resp *http.Response
	maxRetries := 3
	for i := 0; i < maxRetries; i++ {
		resp, err = client.Get(parsedURL.String())
		if err == nil && resp.StatusCode == http.StatusOK {
			break
		}
		time.Sleep(time.Duration(i+1) * time.Second) // 指数退避
	}
	if err != nil {
		return fmt.Errorf("GET请求失败: %w", err)
	}
	defer resp.Body.Close()

	return decodeResponse(resp, result)
}

// 改进后的 Post 方法（兼容原有调用方式）
func Post(targetURL string, bodyParams interface{}, headers map[string]string, result interface{}) error {
	// 自动设置默认 Content-Type（当未显式设置时）
	if _, exists := headers["Content-Type"]; !exists {
		headers["Content-Type"] = "application/json" // 网页6提到的JSON头设置
	}

	// 优化序列化逻辑（支持更多数据类型）
	var bodyBuffer *bytes.Buffer
	switch v := bodyParams.(type) {
	case []byte:
		bodyBuffer = bytes.NewBuffer(v)
	case string:
		bodyBuffer = bytes.NewBufferString(v)
	case io.Reader:
		bodyBytes, err := io.ReadAll(v)
		if err != nil {
			return fmt.Errorf("读取流数据失败: %w", err)
		}
		bodyBuffer = bytes.NewBuffer(bodyBytes)
	default:
		jsonData, err := json.Marshal(v)
		if err != nil {
			return fmt.Errorf("JSON序列化失败: %w", err)
		}
		bodyBuffer = bytes.NewBuffer(jsonData)
	}

	// 创建带上下文的请求（为未来扩展准备）
	req, err := http.NewRequestWithContext(context.Background(),
		"POST", targetURL, bodyBuffer)
	if err != nil {
		return fmt.Errorf("创建请求失败: %w", err)
	}

	// 增强请求头设置（规范大小写处理）
	for k, v := range headers {
		req.Header.Set(http.CanonicalHeaderKey(k), v)
	}

	// 可配置化的 HTTP 客户端（网页6提到的代理扩展点）
	client := &http.Client{
		Timeout:   30 * time.Second,
		Transport: http.DefaultTransport, // 可扩展代理配置
	}

	// 发送请求并处理响应
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("请求执行失败: %w", err)
	}
	defer func() {
		// 确保Body关闭（网页2提到的资源释放）
		io.Copy(io.Discard, resp.Body) // 清空未读内容
		resp.Body.Close()
	}()

	// 处理非200状态码（网页5提到的错误处理）
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		errorBody, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))
		return &HTTPError{
			StatusCode: resp.StatusCode,
			Status:     resp.Status,
			Body:       string(errorBody),
		}
	}

	// 增强响应解码（网页8提到的错误捕获）
	if result != nil {
		if err := json.NewDecoder(resp.Body).Decode(result); err != nil {
			return fmt.Errorf("响应解析失败: %w", err)
		}
	}
	return nil
}

// 新增自定义错误类型（网页5提到的错误处理）
type HTTPError struct {
	StatusCode int
	Status     string
	Body       string
}

func (e *HTTPError) Error() string {
	return fmt.Sprintf("HTTP错误 %d: %s | 响应内容: %s",
		e.StatusCode, e.Status, e.Body)
}

// ================== 辅助函数 ==================

// signParams 参数签名（HMAC-SHA256）
func signParams(params map[string]string, secret string) map[string]string {
	// 参数排序
	keys := make([]string, 0, len(params))
	for k := range params {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	// 拼接参数
	var builder strings.Builder
	for _, k := range keys {
		builder.WriteString(k)
		builder.WriteString("=")
		builder.WriteString(params[k])
		builder.WriteString("&")
	}
	queryString := strings.TrimSuffix(builder.String(), "&")

	// HMAC-SHA256签名
	h := hmac.New(sha256.New, []byte(secret))
	h.Write([]byte(queryString))
	signature := hex.EncodeToString(h.Sum(nil))

	params["signature"] = signature
	return params
}

func decodeResponse(resp *http.Response, result interface{}) error {
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("响应状态码异常: %d", resp.StatusCode)
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("读取响应体失败: %w", err)
	}

	if err := json.Unmarshal(body, result); err != nil {
		return fmt.Errorf("响应解析失败: %w", err)
	}
	return nil
}

// ================== 原有工具函数 ==================

func WrapJSON(event string, amount int) (string, error) {
	data := models.EventData{
		Event: event,
		Data: struct {
			Amount int `json:"amount"`
		}{
			Amount: amount,
		},
	}

	jsonBytes, err := json.Marshal(data)
	if err != nil {
		return "", err
	}

	return string(jsonBytes), nil
}

func GenerateUUID() string {
	return uuid.New().String()
}

func Exists(arr []int, num int) bool {
	for _, value := range arr {
		if value == num {
			return true
		}
	}
	return false
}

// 判断字符串是否存在msgId数组中（使用Map）
func StrExists(strIds []string, target string) bool {
	// 创建map存储msgId
	msgIDSet := make(map[string]struct{})
	for _, id := range strIds {
		msgIDSet[id] = struct{}{}
	}
	// 检查目标字符串是否存在
	_, exists := msgIDSet[target]
	return exists
}

// 带毫秒的转换函数
func ConvertNullTimeToMicroTimestamp(nt sql.NullTime) (int64, bool) {
	if !nt.Valid {
		return 0, false
	}
	return nt.Time.UnixNano() / 1e6, true
}

func ConvertNullTimeToTimestamp(nt sql.NullTime) int64 {
	if !nt.Valid {
		return 0 // 或返回错误/自定义默认值
	}
	return nt.Time.Unix() // 返回秒级时间戳
}
